from ctypes import (
    windll,
    wintypes,
    Structure,
    c_ulong,
    c_bool,
    c_int,
    byref,
    create_unicode_buffer,
    sizeof,
    WINFUNCTYPE,
    POINTER,
)
import difflib

user32 = windll.user32
GetCursorPos = user32.GetCursorPos
WindowFromPoint = user32.WindowFromPoint
GetWindowTextW = user32.GetWindowTextW
GetWindowTextLength = user32.GetWindowTextLengthW
GetParent = user32.GetParent
SetSystemCursor = user32.SetSystemCursor
SetWindowPos = user32.SetWindowPos
GetSystemMetrics = user32.GetSystemMetrics
IsWindowVisible = user32.IsWindowVisible
EnumWindows = user32.EnumWindows
EnumWindowsProc = WINFUNCTYPE(c_bool, POINTER(c_int), POINTER(c_int))
FindWindowW = user32.FindWindowW
GetWindowRect = user32.GetWindowRect
OCR_NORMAL = 32512
SWP_NOSIZE = 1
SWP_NOZORDER = 4


class Point(Structure):
    _fields_ = [("x", c_ulong), ("y", c_ulong)]


def get_cursor_pos():  # 获取鼠标位置
    point = Point()
    GetCursorPos(byref(point))
    return point.x, point.y


def get_hwnd_from_pos(t=None, x=None, y=None):  # 根据坐标获取句柄
    point = Point()
    if isinstance(t, tuple):
        point.x, point.y = t[0], t[1]
    elif isinstance(x, int) and isinstance(y, int):
        point.x, point.y = x, y
    else:
        return None
    hwnd = WindowFromPoint(point)
    return hwnd


def get_title(hwnd):
    length = GetWindowTextLength(hwnd) + 1
    buffer = create_unicode_buffer(length)
    GetWindowTextW(hwnd, buffer, length)
    return hwnd, buffer.value


def get_title_p(hwnd):  # 离最近的有标题的父辈句柄
    length = GetWindowTextLength(hwnd) + 1
    while length == 1 and hwnd != 0:
        hwnd = GetParent(hwnd)
        length = GetWindowTextLength(hwnd) + 1
    buffer = create_unicode_buffer(length)
    GetWindowTextW(hwnd, buffer, length)
    return hwnd, buffer.value


def get_title_pp(hwnd):  # 离最远的排最后的父辈句柄
    length = GetWindowTextLength(hwnd) + 1
    while True:
        if GetParent(hwnd) == 0:
            break
        hwnd = GetParent(hwnd)
        length = GetWindowTextLength(hwnd) + 1
    buffer = create_unicode_buffer(length)
    GetWindowTextW(hwnd, buffer, length)
    return hwnd, buffer.value


def move_window(hwnd, x: int, y: int):
    SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER)


def get_window_rect(hwnd):
    rect = wintypes.RECT()
    GetWindowRect(hwnd, byref(rect))
    return rect.left, rect.top, rect.right, rect.bottom


def get_screen_geometry():
    return GetSystemMetrics(0), GetSystemMetrics(1)


def title_fuzzy_search(text):
    titles = []
    def foreach_window(hwnd, lParam):
        if IsWindowVisible(hwnd):
            length = GetWindowTextLength(hwnd)
            buff = create_unicode_buffer(length + 1)
            GetWindowTextW(hwnd, buff, length + 1)
            titles.append(buff.value)
        return True
    EnumWindows(EnumWindowsProc(foreach_window), 0)
    titles = list(filter(None,titles))
    return difflib.get_close_matches(text, titles, 1, cutoff=0.5)

def find_window(title):
    hwnd = FindWindowW(None,title)
    return hwnd
